home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Practical Algorithms for Image Analysis
/
Practical Algorithms for Image Analysis.iso
/
TARFILE.GZ
/
tarfile
/
ch_3.6
/
subsampleNI
/
subsampleNI.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-09-11
|
13KB
|
374 lines
/*
* subsampleNI.c
*
* Practical Algorithms for Image Analysis
*
* Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
*/
/* subsampleNI: program performs image size reduction, in particular
* enabling non-integer subsampling
*/
#define DFLTPCT 50.0 /* default subsample percentage */
#define G_THRESHPCT_M 100.0 /* default gray thresh pct for matched fltr */
#define G_THRESHPCT_R 100.0 /* default gray thresh pct for rect fltr */
#define G_THRESHPCT_G 60.0 /* default gray thresh pct for Gaussian fltr */
#define MAXCOEF 100.0 /* maximum filter coefficient value */
#define RESOLUTION 8 /* subpixel res. of filter */
#define FLTR_VAR_NUM 2.0 /* num. of var.s at max width of fltr */
#define MAX_BITS_QUANT 8 /* max. bits of gray quantization */
#define ABSF(A) ((A > 0.0) ? A:-(A)) /* floating absolute value */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <images.h>
#include <tiffimage.h>
#include <math.h>
extern void print_sos_lic ();
int shrinkGG (unsigned char **, long, long, unsigned char **, long *, long *,
double, long, double, double);
long usage (short);
long input (int, char **, double *, long *, long *, long *, double *,
double *, short *, short *);
int argc;
char *argv[];
double *pct; /* subsample percentage */
long *wSize, *hSize; /* subsampled image size: width, height */
long *fltrSize; /* filter sidelength */
double *fltrVarNum; /* num. of var.s at max width of fltr */
double *threshG; /* gray-scale threshold scale factor */
short *qfFlag; /* quick filter if =1, or default if 0 */
short *gfFlag; /* Gaussian filter if =1, or default if 0 */
main (
int argc,
char *argv[])
{
Image *imgI, *imgO; /* I/O image structures */
unsigned char **imgIn, **imgGray; /* input and gray images */
long widthIn, heightIn; /* image size */
long widthOut, heightOut;
long fltrSize; /* sidelength of filter */
long xSize, ySize; /* subsampled image size */
double pct, /* percentage of row/cols to remain */
rate, /* subsample rate */
xRate, yRate, /* rate to reach desired size */
threshG, /* gray-scale threshold scale factor */
fltrVarNum, /* num of var.s at max width of fltr */
fltrVar; /* variance of Gaussian filter [pix] */
short qfFlag; /* quick filter if =1, or dflt */
short gfFlag; /* quick filter if =1, or dflt */
if (input (argc, argv, &pct, &xSize, &ySize, &fltrSize,
&fltrVarNum, &threshG, &qfFlag, &gfFlag) < 0)
return (-1);
/* allocate input image memory */
imgI = ImageIn (argv[1]);
imgIn = ImageGetPtr (imgI);
heightIn = ImageGetHeight (imgI);
widthIn = ImageGetWidth (imgI);
/* set threshold contrast factors depending on slow/quick */
if (threshG == -1.0) {
if (qfFlag == 1)
threshG = G_THRESHPCT_R;
else if (gfFlag == 1)
threshG = G_THRESHPCT_G;
else
threshG = G_THRESHPCT_M;
}
threshG = threshG / 100.0;
/* determine subsampling rate, filter parameters */
if (xSize == -1 && ySize == -1)
rate = 100.0 / pct;
else {
xRate = (double) widthIn / (double) xSize;
yRate = (double) heightIn / (double) ySize;
if (xRate > yRate)
rate = xRate;
else
rate = yRate;
if (rate < 1.0)
rate = 1.0;
pct = 100.0 / rate;
}
if (fltrSize == 0)
fltrSize = 2 * (long) ((100.0 / pct - 1.0) / 2.0 + 0.9999) + 1;
if (fltrSize % 2 == 0)
fltrSize += 1;
fltrVar = ((double) (fltrSize - 1)) / (2.0 * fltrVarNum);
if (fltrVar == 0.0)
fltrVar = 1.0;
/* determine output size and allocate output image */
heightOut = (long) ((heightIn - fltrSize) / rate) + 1;
widthOut = (long) ((widthIn - fltrSize) / rate) + 1;
imgO = ImageAlloc (heightOut, widthOut, 8);
imgGray = ImageGetPtr (imgO);
printf ("Image input size = %dx%d, filter size = %dx%d\n",
widthIn, heightIn, fltrSize, fltrSize);
/* perform subsampling */
shrinkGG (imgIn, widthIn, heightIn, imgGray, &widthOut, &heightOut,
pct, fltrSize, threshG, fltrVar);
/* write output image to file */
ImageOut (argv[2], imgO);
printf ("Image output size = %dx%d\n", widthOut, heightOut);
return (0);
}
/* SHRINKGG: shrink program for gray-scale input image uses Gaussian filter
*/
int
shrinkGG (imgIn, widthIn, heightIn, imgOut, widthOut, heightOut,
pct, fltrSize, threshG, fltrVar)
unsigned char **imgIn, **imgOut; /* input and output images */
long widthIn, heightIn;
long *widthOut, *heightOut;
double pct; /* percentage of row/cols to remain */
long fltrSize; /* sidelength of filter */
double threshG; /* gray-scale threshold scale factor */
double fltrVar; /* variance of Gaussian filter [pix] */
{
long halfFltr, /* half filter sidelength */
xOut, yOut; /* output image coord.s */
long temp; /* value of pixel before normaliz. */
long xMinW, xMaxW, /* min and max window coord.s */
yMaxW, yMinW;
double xIn, yIn; /* input image subpixel coord.s */
long xInMid, yInMid; /* integer middle of fltr on input */
double rate; /* subsample rate */
long **coef; /* fltr coefs for (res * size) dists */
long halfCoef, /* no. coef.s in half filter */
halfCoefPHalf; /* no. coef.s in half plus half fltr */
double exponent; /* exponent of Gaussian for filter */
long sum, /* result of filter conv. at pt */
sumCoef; /* sum of coef.s applied at point */
struct point end; /* bottom right of image */
double endYMHalf, endXMHalf; /* last x,y coef, minus half filter */
double distance; /* dist * res. on Gaussian filter */
long distX, distY; /* x,y dist.s within filter mask */
double xInR, yInR; /* yIn,xIn scaled by RESOLUTION */
long i, j; /* increment */
long iR, jR; /* increment scaled by RESOLUTION */
long xMinWR, yMinWR; /* min. of mask on scaled coord.s */
double rateR; /* scaled rate */
double sqrt (), exp (), log2 ();
long nbrSum; /* sum of coef.s for ONs in nbrhd */
/* compute filter coef.s */
halfFltr = (fltrSize - 1) / 2;
halfCoef = halfFltr * RESOLUTION;
halfCoefPHalf = halfFltr * RESOLUTION + (RESOLUTION + 1) / 2;
if ((coef = (long **) calloc (halfCoefPHalf + 1, sizeof (long *))) == NULL)
exit (1);
for (i = 0; i <= halfCoefPHalf; i++)
if ((coef[i] = (long *) calloc (halfCoefPHalf + 1, sizeof (long))) == NULL)
exit (1);
for (i = 0; i <= halfCoefPHalf; i++) {
exponent = ((double) (i)) / (RESOLUTION * fltrVar);
coef[0][i] = coef[i][0]
= (long) (MAXCOEF * exp (-exponent * exponent / 2.0) + 0.5);
}
for (j = 1; j <= halfCoefPHalf; j++) {
for (i = 1; i <= halfCoefPHalf; i++) {
distance = sqrt ((double) (i * i + j * j));
exponent = distance / (RESOLUTION * fltrVar);
coef[j][i] = (long) (MAXCOEF * exp (-exponent * exponent / 2.0) + 0.5);
}
}
/* filter and subsample */
end.x = widthIn - 1 - halfFltr;
end.y = heightIn - 1 - halfFltr;
endYMHalf = (double) (end.y - halfFltr);
endXMHalf = (double) (end.x - halfFltr);
yInR = halfFltr * RESOLUTION;
rate = 100.0 / pct;
rateR = rate * RESOLUTION;
for (yIn = halfFltr, yOut = 0; yIn < endYMHalf; yIn += rate, yInR += rateR) {
yInMid = (long) (yIn + 0.5);
yMinW = yInMid - halfFltr;
yMaxW = yInMid + halfFltr;
yMinWR = yMinW * RESOLUTION;
xInR = halfFltr * RESOLUTION;
for (xIn = halfFltr, xOut = 0; xIn < endXMHalf; xIn += rate, xInR += rateR) {
xInMid = (long) (xIn + 0.5);
xMinW = xInMid - halfFltr;
xMaxW = xInMid + halfFltr;
xMinWR = xMinW * RESOLUTION;
sum = sumCoef = nbrSum = 0;
for (j = yMinW, jR = yMinWR; j <= yMaxW; j++, jR += RESOLUTION) {
distY = (long) (ABSF (yInR - jR) + 0.5);
for (i = xMinW, iR = xMinWR; i <= xMaxW; i++, iR += RESOLUTION) {
distX = (long) (ABSF (xInR - iR) + 0.5);
if (imgIn[j][i] != 0)
sum += coef[distY][distX] * imgIn[j][i];
sumCoef += coef[distY][distX];
}
}
if (sum != 0) {
temp = (long) ((double) sum / (threshG * sumCoef) + 0.5);
if (temp > 255)
temp = 255;
imgOut[yOut][xOut++] = (unsigned char) temp;
}
else
imgOut[yOut][xOut++] = 0;
}
yOut++;
}
*heightOut = yOut;
return (0);
}
/* USAGE: function gives instructions on usage of program
* usage: usage (flag)
* When flag is 1, the long message is given, 0 gives short.
*/
long
usage (flag)
short flag; /* flag =1 for long message; =0 for short message */
{
/* print short usage message or long */
printf ("usage: subsampleNI in.img out.img\n");
printf ("\t\t[-p PCT <%4.1f%%>] OR ([-h HEIGHT] AND/OR [-w WIDTH])\n",
DFLTPCT);
printf ("\t\t[-tg GRAY CONTRAST <%3.0f%%>]\n", G_THRESHPCT_M);
printf ("\t\t[-f FLTRSIZE]\n");
printf ("\t\t[-qf QUICK FILTER (rectangular filter)]\n");
printf ("\t\t[-gf GAUSSIAN FILTER (instead of default matched filter]\n");
printf ("\t\t[-v VARIANCE MULTIPLE (for Gaussian) <%2.0f>]\n", FLTR_VAR_NUM);
if (flag == 0)
return (-1);
printf ("\nSUBSAMPLENI filters and subsamples to chosen size.\n");
printf ("\nFLAGS:\n");
printf ("\t-p PCT percentage size of image sidelengths to retain.\n");
printf ("\t-h HEIGHT -w WIDTH size of image sidelengths to retain.\n");
printf ("\t\tPCT can be used alone OR (HEIGHT AND/OR WIDTH). When both\n");
printf ("\t\tHEIGHT and WIDTH are used, the smaller reduction is made.\n");
printf ("\t-tg GRAY CONTRAST PCT smaller number gives darker image.\n");
printf ("\t\tSetting -tg to 100%%, turns off constrasting.\n");
printf ("\t-f FILTER SIZE is square mask size low-pass filter (>= 3).\n");
printf ("\t-qf QUICK FILTER - quicker rectangular filter instead of\n");
printf ("\t\tdefault matched filter.\n");
printf ("\t\tIf filter size is set to 1, this is the quickest and\n");
printf ("\t\tugliest result.\n");
printf ("\t\tNote that this filter is used automatically instead\n");
printf ("\t\tof default for filter sizes larger than 5x5.\n");
printf ("\t-gf GAUSSIAN FILTER - symmetric Gaussian filter instead of\n");
printf ("\t\tdefault matched filter.\n");
printf ("\t-v VARIANCE MULTIPLE is no. of variances of Gaussian filter\n");
printf ("\t\tat maximum radius in filter window (0 gives uniform wting).\n");
printf ("\t-L: print Software License for this module\n");
return (-1);
}
/* INPUT: function reads input parameters
* usage: input (argc, argv, &pct, &wSize, &hSize,
* &fltrSize, &fltrVar, &threshG,
* &gFlag, &qfFlag, &gfFlag)
*/
#define USAGE_EXIT(VALUE) {usage (VALUE); return (-1);}
long
input (argc, argv, pct, wSize, hSize, fltrSize, fltrVarNum, threshG,
qfFlag, gfFlag)
int argc;
char *argv[];
double *pct; /* subsample percentage */
long *wSize, *hSize; /* subsampled image size: width, height */
long *fltrSize; /* filter sidelength */
double *fltrVarNum; /* num. of var.s at max width of fltr */
double *threshG; /* gray-scale threshold scale factor */
short *qfFlag; /* quick filter if =1, or default if 0 */
short *gfFlag; /* Gaussian filter if =1, or default if 0 */
{
long n;
double atof ();
if (argc < 3)
USAGE_EXIT (-1);
*pct = DFLTPCT;
*wSize = *hSize = -1;
*fltrSize = 1;
*threshG = -1.0;
*fltrVarNum = FLTR_VAR_NUM;
*qfFlag = 0;
*gfFlag = 0;
for (n = 3; n < argc; n++) {
if (strcmp (argv[n], "-p") == 0) {
if (++n == argc || argv[n][0] == '-')
USAGE_EXIT (-1);
*pct = atof (argv[n]);
}
else if (strcmp (argv[n], "-w") == 0) {
if (++n == argc || argv[n][0] == '-')
USAGE_EXIT (-1);
*wSize = atol (argv[n]);
}
else if (strcmp (argv[n], "-h") == 0) {
if (++n == argc || argv[n][0] == '-')
USAGE_EXIT (-1);
*hSize = atol (argv[n]);
}
else if (strcmp (argv[n], "-f") == 0) {
if (++n == argc || argv[n][0] == '-')
USAGE_EXIT (-1);
*fltrSize = atol (argv[n]);
}
else if (strcmp (argv[n], "-tg") == 0) {
if (++n == argc || argv[n][0] == '-')
USAGE_EXIT (-1);
*threshG = atof (argv[n]);
}
else if (strcmp (argv[n], "-v") == 0) {
if (++n == argc || argv[n][0] == '-')
USAGE_EXIT (-1);
*fltrVarNum = atof (argv[n]);
}
else if (strcmp (argv[n], "-qf") == 0)
*qfFlag = 1;
else if (strcmp (argv[n], "-gf") == 0)
*gfFlag = 1;
else if (strcmp (argv[n], "-L") == 0) {
print_sos_lic ();
exit (0);
}
else
USAGE_EXIT (-1);
}
return (0);
}